home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UStream.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  22.9 KB  |  854 lines  |  [TEXT/MPS ]

  1. // UStream.cp 
  2. // Copyright © 1990-1991 by Apple Computer Inc. All rights reserved.
  3. // Originally written by Larry S. Rosenstein.  Used by permission 
  4.  
  5. // Types defining the table mapping old class IDs (found in the stream) to new class IDs
  6. // for the classes linked with the application.
  7.  
  8. #ifndef __USTREAM__
  9. #include <UStream.h>
  10. #endif
  11.  
  12. #ifndef __GEOMETRY__
  13. #include <Geometry.h>
  14. #endif
  15.  
  16. #ifndef __UFILE__
  17. #include <UFile.h>
  18. #endif
  19.  
  20. #ifndef __UFAILURE__
  21. #include <UFailure.h>
  22. #endif
  23.  
  24. #ifndef __TEXTEDIT__
  25. #include <TextEdit.h>
  26. #endif
  27.  
  28. #ifndef __OSUTILS__
  29. #include <OSUtils.h>
  30. #endif
  31.  
  32. #ifndef __UMACAPPUTILITIES__
  33. #include <UMacAppUtilities.h>
  34. #endif
  35.  
  36. #ifndef __UPATCH__
  37. #include <UPatch.h>
  38. #endif
  39.  
  40. #ifndef __UMEMORY__
  41. #include <UMemory.h>
  42. #endif
  43.  
  44. #ifndef __FILES__
  45. #include <Files.h>
  46. #endif
  47.  
  48. #ifndef __ERRORS__
  49. #include <Errors.h>
  50. #endif
  51.  
  52. #ifndef __RESOURCES__
  53. #include <Resources.h>
  54. #endif
  55.  
  56.  
  57. const short kMaxClasses = 8000;
  58.  
  59. typedef struct ClassIDEntry
  60. {
  61.     ObjClassID fOldID;
  62.     ObjClassID fNewID;
  63. };
  64.  
  65.  
  66. typedef ClassIDEntry ClassArray[kMaxClasses], * PClassIDEntry;
  67. typedef PClassIDEntry* HClassArray;
  68.  
  69. //--------------------------------------------------------------------------------------------------
  70. #pragma segment MAStreamUtil
  71.  
  72. pascal Boolean TStream::AtEnd(void)
  73. {
  74.     if (this->GetPosition() >= this->GetSize())
  75.         return TRUE;
  76.     else
  77.         return FALSE;
  78. }
  79.  
  80. //--------------------------------------------------------------------------------------------------
  81. #pragma segment MAStreamFields
  82.  
  83. pascal void TStream::Fields(TObject* obj)        // override 
  84. {
  85.     obj->DoToField("TStream", NULL, bClass);
  86.     obj->DoToField("fClassMapSize", &fClassMapSize, bInteger);
  87.     obj->DoToField("fClassMap", &fClassMap, bHandle);
  88.     inherited::Fields(obj);
  89. }
  90.  
  91. //--------------------------------------------------------------------------------------------------
  92. #pragma segment MAStreamFree
  93.  
  94. pascal void TStream::Free(void)                    // override 
  95. {
  96.     fClassMap = DisposeIfHandle(fClassMap);
  97.     inherited::Free();
  98. }
  99.  
  100. //--------------------------------------------------------------------------------------------------
  101. #pragma segment MAStreamUtil
  102.  
  103. pascal long TStream::GetPosition(void)
  104. {
  105.     return 0;
  106. }
  107.  
  108. //--------------------------------------------------------------------------------------------------
  109. #pragma segment MAStreamUtil
  110.  
  111. pascal long TStream::GetSize(void)
  112. {
  113.     return 0;
  114. }
  115.  
  116. //--------------------------------------------------------------------------------------------------
  117. #pragma segment MAStreamCreate
  118.  
  119. pascal void TStream::Initialize(void)            // override 
  120.  
  121. {
  122.     inherited::Initialize();
  123.     fClassMap = NULL;
  124.     fClassMapSize = 0;
  125. }
  126.  
  127. //--------------------------------------------------------------------------------------------------
  128. #pragma segment MAStreamCreate
  129.  
  130. pascal void TStream::IStream(void)
  131. {
  132.     FailInfo fi;
  133.  
  134.     if (fi.Try())                        // In case allocation fails, object is freed.
  135.     {
  136.         this->IObject();
  137.         fClassMap = NewPermHandle(0);
  138.         fi.Success();
  139.     }
  140.     else    // Recover
  141.     {
  142.         this->Free();                            // Free the stream if it can't be initialized
  143.         fi.ReSignal();
  144.     }
  145. }
  146.  
  147. //--------------------------------------------------------------------------------------------------
  148. #pragma segment MAStreamUtil
  149.  
  150. // This returns the new class ID given a class ID found
  151. // in the stream, or kNilClass if it wasn't found.
  152. // It does a simple linear search.
  153. pascal ObjClassID TStream::LookupClassID(ObjClassID id)
  154. {
  155.     if (id != kNilClass)
  156.         for (short i = 0; i < fClassMapSize; ++i)
  157.             if (((ClassArray) * fClassMap)[i].fOldID == id)
  158.                 return ((ClassArray) * fClassMap)[i].fNewID;
  159.     return kNilClass;
  160. }
  161.  
  162. //--------------------------------------------------------------------------------------------------
  163. #pragma segment MAStreamNever
  164.  
  165. pascal void TStream::ReadBytes(void* ,
  166.                                long)
  167. {
  168.     this->SubClassResponsibility();
  169. }
  170.  
  171. //--------------------------------------------------------------------------------------------------
  172. #pragma segment MAStreamRead
  173.  
  174. // The trick here is that characters are
  175. // represented as 2 bytes, with the actual
  176. // data in the low order byte.
  177. pascal void TStream::ReadCharacter(short& data)
  178. {
  179.     this->ReadBytes((char*)(&data + 1), 1);
  180. }
  181.  
  182. //--------------------------------------------------------------------------------------------------
  183. #pragma segment MAStreamRead
  184.  
  185. pascal void TStream::ReadInteger(short& data)
  186. {
  187.     this->ReadBytes(&data, sizeof(short));
  188. }
  189.  
  190. //--------------------------------------------------------------------------------------------------
  191. #pragma segment MAStreamRead
  192.  
  193. pascal void TStream::ReadLong(long& data)
  194. {
  195.     this->ReadBytes(&data, sizeof(long));
  196. }
  197.  
  198. //--------------------------------------------------------------------------------------------------
  199. #pragma segment MAStreamRead
  200.  
  201. pascal void TStream::ReadObject(TObject** data,
  202.                                 Boolean& known)
  203. {
  204.     ObjClassID streamID;                        // Class ID in stream. 
  205.     long sizePosition;
  206.     long objectSize;
  207.     MAName className;
  208.     ObjClassID currentID;                        // Class ID in program. 
  209.  
  210.     this->ReadBytes(&streamID, sizeof(ObjClassID));// Read the object's class ID. 
  211.  
  212.     sizePosition = this->GetPosition();            // Read its size and remember the current position.
  213.     this->ReadLong(objectSize);
  214.  
  215.     this->ReadString(className, sizeof(MAName));// Read its name. 
  216.  
  217.     if (className.IsEmpty())                    // No class name. Must have seen the class
  218.     // before, so convert the streamID to the
  219.     // currentID.
  220.         currentID = this->LookupClassID(streamID);
  221.     else
  222.     {                                            // Get ID from name ... 
  223.         currentID = GetClassIDFromName(className);
  224.         this->RegisterClassID(streamID, currentID);// ... and register the IDs. 
  225.     }
  226.  
  227.     if (currentID == kNilClass)                    // Don't know about the class. 
  228.     {
  229.         *data = NULL;
  230.         // If the streamID is kNilClass then the object was realy
  231.         //    NULL, which is a known object, otherwise the class
  232.         //    isn't available.
  233.         known = streamID == kNilClass;
  234.  
  235.         // Skip over the object's data. 
  236.         this->SetPosition(sizePosition + objectSize);// Skip over its data. 
  237.     }
  238.     else
  239.     {                                            // Create the object. 
  240.         *data = NULL;
  241.         *data = NewObjectByClassId(currentID);
  242.         known = TRUE;
  243.     }
  244. }
  245.  
  246. //--------------------------------------------------------------------------------------------------
  247. #pragma segment MAStreamRead
  248.  
  249. pascal void TStream::ReadPoint(Point& data)
  250. {
  251.     this->ReadBytes(&data, sizeof(Point));
  252. }
  253.  
  254. //--------------------------------------------------------------------------------------------------
  255. #pragma segment MAStreamRead
  256.  
  257. pascal void TStream::ReadRect(Rect& data)
  258. {
  259.     this->ReadBytes(&data, sizeof(Rect));
  260. }
  261.  
  262. //--------------------------------------------------------------------------------------------------
  263. #pragma segment MAStreamRead
  264.  
  265. pascal void TStream::ReadStreamObject(TObject** data,
  266.                                       Boolean& known)
  267. {
  268.     this->ReadObject(data, known);    // Create an uninitialized object. 
  269.  
  270.     if (*data)                                    // If we got an object, then tell it to initialize itself.
  271.         (*data)->ReadFrom(this);
  272. }
  273.  
  274. //--------------------------------------------------------------------------------------------------
  275. #pragma segment MAStreamRead
  276.  
  277. pascal void TStream::ReadString(String& data,
  278.                                 short maxSize)
  279. {
  280.     this->ReadBytes(&data, 1);                    // Read the length byte. 
  281.  
  282.     if (data.Length() + 1 > maxSize)
  283.         FailOSErr(paramErr);                    // Can't read that many bytes. 
  284.     else
  285.         this->ReadBytes(&data[1], (long)data.Length());
  286. }
  287.  
  288. //--------------------------------------------------------------------------------------------------
  289. #pragma segment MAStreamUtil
  290.  
  291. // This simply adds the mapping to the end of the list.
  292. // It does not check to see if the mapping exists already.
  293. pascal void TStream::RegisterClassID(ObjClassID oldID,
  294.                                      ObjClassID newID)
  295. {
  296.     if (oldID != kNilClass)
  297.     {
  298.         ++fClassMapSize;
  299.         SetHandleSize(fClassMap, fClassMapSize * sizeof(ClassIDEntry));
  300.  
  301.         ((ClassArray) * fClassMap)[fClassMapSize].fOldID = oldID;
  302.         ((ClassArray) * fClassMap)[fClassMapSize].fNewID = newID;
  303.     }
  304. }
  305.  
  306. //--------------------------------------------------------------------------------------------------
  307. #pragma segment MAStreamUtil
  308.  
  309. pascal void TStream::SetPosition(long newPosition)
  310. {
  311. }
  312.  
  313. //--------------------------------------------------------------------------------------------------
  314. #pragma segment MAStreamUtil
  315.  
  316. pascal void TStream::SetSize(long newSize)
  317. {
  318. }
  319.  
  320. //--------------------------------------------------------------------------------------------------
  321. #pragma segment MAStreamWrite
  322.  
  323. pascal void TStream::WriteCharacter(short data)
  324. {
  325.     this->WriteBytes((char*)(&data + 1), 1);    // Again, the data is in the low order byte.
  326. }
  327.  
  328. //--------------------------------------------------------------------------------------------------
  329. #pragma segment MAStreamNever
  330.  
  331. pascal void TStream::WriteBytes(const void* ,
  332.                                 long )
  333. {
  334.     this->SubClassResponsibility();
  335. }
  336.  
  337. //--------------------------------------------------------------------------------------------------
  338. #pragma segment MAStreamWrite
  339.  
  340. pascal void TStream::WriteInteger(short data)
  341.  
  342. {
  343.     this->WriteBytes(&data, sizeof(short));
  344. }
  345.  
  346. //--------------------------------------------------------------------------------------------------
  347. #pragma segment MAStreamWrite
  348.  
  349. pascal void TStream::WriteLong(long data)
  350.  
  351. {
  352.     this->WriteBytes(&data, sizeof(long));
  353. }
  354.  
  355. //--------------------------------------------------------------------------------------------------
  356. #pragma segment MAStreamWrite
  357.  
  358. pascal void TStream::WriteObject(TObject* data,
  359.                                  long& sizePosition)
  360. {
  361.     ObjClassID streamID;
  362.     MAName className;
  363.  
  364.     if (data)
  365.         streamID = data->GetClass();
  366.     else
  367.         streamID = kNilClass;
  368.  
  369.     this->WriteBytes(&streamID, sizeof(ObjClassID));// Write the class ID. 
  370.  
  371.     sizePosition = this->GetPosition();            // Remember the position of the object size
  372.     // in the stream.
  373.  
  374.     this->WriteLong(MAXLONGINT);                // Write a dummy size (maximum object size).
  375.  
  376.     if ((data) && (this->LookupClassID(streamID) == kNilClass))
  377.     // data is not NULL, and this is the first object of the class. 
  378.     {
  379.         data->GetClassName(className);            // Get the actual class name. 
  380.  
  381.         // Register the ID, so we don't write the class name the next time
  382.         //    we write an object of this class.  The second parameter
  383.         //    doesn't matter,  as long as it isn't kNilClass.
  384.         this->RegisterClassID(streamID, streamID);
  385.     }
  386.     else
  387.         className = "";
  388.  
  389.     this->WriteString(className);                // Write the class name (which may be empty).
  390. }
  391.  
  392. //--------------------------------------------------------------------------------------------------
  393. #pragma segment MAStreamWrite
  394.  
  395. // This fills in the object's size at the position passed in. 
  396. pascal void TStream::WriteObjectSize(long sizePosition)
  397. {
  398.     long currentPosition = this->GetPosition();    // Remember where we are. 
  399.     this->SetPosition(sizePosition);            // Go back to position of size. 
  400.  
  401.     this->WriteLong(currentPosition - sizePosition);// Write the size. 
  402.  
  403.     this->SetPosition(currentPosition);            // Go back to where we were. 
  404. }
  405.  
  406. //--------------------------------------------------------------------------------------------------
  407. #pragma segment MAStreamWrite
  408.  
  409. pascal void TStream::WritePoint(Point data)
  410. {
  411.     this->WriteBytes(&data, sizeof(Point));
  412. }
  413.  
  414. //--------------------------------------------------------------------------------------------------
  415. #pragma segment MAStreamWrite
  416.  
  417. pascal void TStream::WriteRect(const Rect& data)
  418. {
  419.     this->WriteBytes(&data, sizeof(Rect));
  420. }
  421.  
  422. //--------------------------------------------------------------------------------------------------
  423. #pragma segment MAStreamWrite
  424.  
  425. pascal void TStream::WriteStreamObject(TObject* data)
  426. {
  427.     long sizePosition;
  428.  
  429.     this->WriteObject(data, sizePosition);        // Write the object header. 
  430.  
  431.     if (data)                                    // Write the private data. 
  432.         data->WriteTo(this);
  433.  
  434.     this->WriteObjectSize(sizePosition);        // Write the object size. 
  435. }
  436.  
  437. //--------------------------------------------------------------------------------------------------
  438. #pragma segment MAStreamWrite
  439.  
  440. pascal void TStream::WriteString(const String& data)
  441. {
  442.     this->WriteBytes(&data, ((long)data.Length()) + 1);// + 1 to include length byte. 
  443. }
  444.  
  445. //--------------------------------------------------------------------------------------------------
  446. #pragma segment MAStreamFields
  447.  
  448. pascal void TFileStream::Fields(TObject* obj)    // override 
  449. {
  450.     obj->DoToField("TFileStream", NULL, bClass);
  451.     obj->DoToField("fFile", &fFile, bObject);
  452.     inherited::Fields(obj);
  453. }
  454.  
  455. //--------------------------------------------------------------------------------------------------
  456. #pragma segment MAStreamUtil
  457.  
  458. pascal long TFileStream::GetPosition(void)        // override 
  459. {
  460.     long itsDataMark;
  461.  
  462.     FailNIL(fFile);
  463.     FailOSErr(fFile->GetDataMark(itsDataMark));    // Call the TFile method. 
  464.     return itsDataMark;                            // Return the result. 
  465. }
  466.  
  467. //--------------------------------------------------------------------------------------------------
  468. #pragma segment MAStreamUtil
  469.  
  470. pascal long TFileStream::GetSize(void)            // override 
  471. {
  472.     long itsDataLength;
  473.  
  474.     FailNIL(fFile);                                // ??? or just return 0
  475.     FailOSErr(fFile->GetDataLength(itsDataLength));        // Call the TFile method. 
  476.     return itsDataLength;                        // Return the result. 
  477. }
  478.  
  479. //--------------------------------------------------------------------------------------------------
  480. #pragma segment MAStreamCreate
  481.  
  482. pascal void TFileStream::Initialize(void)        // override 
  483. {
  484.     inherited::Initialize();
  485.  
  486.     fFile = NULL;
  487. }
  488.  
  489. //--------------------------------------------------------------------------------------------------
  490. #pragma segment MAStreamCreate
  491.  
  492. pascal void TFileStream::IFileStream(TFile* itsFile)
  493. {
  494.     this->IStream();
  495.     fFile = itsFile;                            // Remember the file reference. 
  496. }
  497.  
  498. //--------------------------------------------------------------------------------------------------
  499. #pragma segment MAStreamUtil
  500.  
  501. pascal void TFileStream::SetPosition(long newPosition)// override 
  502. {
  503.     FailNIL(fFile);
  504.     FailOSErr(fFile->SetDataMark(newPosition,fsFromStart));
  505. }
  506.  
  507. //--------------------------------------------------------------------------------------------------
  508. #pragma segment MAStreamUtil
  509.  
  510. pascal void TFileStream::SetSize(long newSize)    // override 
  511. {
  512.     FailNIL(fFile);
  513.     FailOSErr(fFile->SetDataLength(newSize));
  514. }
  515.  
  516. //--------------------------------------------------------------------------------------------------
  517. #pragma segment MAStreamRead
  518.  
  519. pascal void TFileStream::ReadBytes(void* p,
  520.                                    long count)    // override 
  521. {
  522.     FailNIL(fFile);
  523.     FailOSErr(fFile->ReadData(p,count));    
  524. }
  525.  
  526. //--------------------------------------------------------------------------------------------------
  527. #pragma segment MAStreamWrite
  528.  
  529. pascal void TFileStream::WriteBytes(const void* p,
  530.                                     long count)    // override 
  531. {
  532.     FailNIL(fFile);
  533.     FailOSErr(fFile->WriteData(p,count));
  534. }
  535.  
  536. //--------------------------------------------------------------------------------------------------
  537. #pragma segment MAStreamFields
  538.  
  539. pascal void THandleStream::Fields(TObject* obj)    // override 
  540. {
  541.     obj->DoToField("THandleStream", NULL, bClass);
  542.     obj->DoToField("fHandle", &fHandle, bInteger);
  543.     obj->DoToField("fPosition", &fPosition, bLongInt);
  544.     obj->DoToField("fSize", &fSize, bLongInt);
  545.     obj->DoToField("fGrowthSize", &fGrowthSize, bLongInt);
  546.  
  547.     inherited::Fields(obj);
  548. }
  549.  
  550. //--------------------------------------------------------------------------------------------------
  551. #pragma segment MAStreamFree
  552.  
  553. pascal void THandleStream::Free(void)            // override 
  554. {
  555.     this->SetSize(this->GetPosition());            // Trim the handle to its current position. 
  556.     inherited::Free();
  557. }
  558.  
  559. //--------------------------------------------------------------------------------------------------
  560. #pragma segment MAStreamUtil
  561.  
  562. pascal long THandleStream::GetPosition(void)    // override 
  563. {
  564.     return fPosition;
  565. }
  566.  
  567. //--------------------------------------------------------------------------------------------------
  568. #pragma segment MAStreamUtil
  569.  
  570. pascal long THandleStream::GetSize(void)        // override 
  571. {
  572.     return fSize;
  573. }
  574.  
  575. //--------------------------------------------------------------------------------------------------
  576. #pragma segment MAStreamUtil
  577.  
  578. pascal long THandleStream::GrowthSize(long needed)
  579. {
  580.     return Max(fGrowthSize, needed);
  581. }
  582.  
  583. //--------------------------------------------------------------------------------------------------
  584. #pragma segment MAStreamCreate
  585.  
  586. pascal void THandleStream::Initialize(void)        // override 
  587. {
  588.     inherited::Initialize();
  589.  
  590.     fGrowthSize = 1;
  591.     fHandle = NULL;
  592.     fPosition = 0;
  593.     fSize = 0;
  594. }
  595.  
  596. //--------------------------------------------------------------------------------------------------
  597. #pragma segment MAStreamCreate
  598.  
  599. pascal void THandleStream::IHandleStream(Handle itsHandle,
  600.                                          long growth)
  601. {
  602.     this->IStream();
  603.  
  604.     fHandle = itsHandle;
  605.     fGrowthSize = growth;
  606.     fPosition = 0;
  607.     fSize = GetHandleSize(itsHandle);
  608. }
  609.  
  610. //--------------------------------------------------------------------------------------------------
  611. #pragma segment MAStreamUtil
  612.  
  613. pascal void THandleStream::SetPosition(long newPosition)// override 
  614. {
  615.     OSErr err;
  616.  
  617.     if (newPosition < 0)                        // Same error returned by File Manager. 
  618.         FailOSErr(posErr);
  619.     else if (newPosition > fSize)                // Hit the end of the stream. 
  620.     {
  621.         newPosition = fSize;                    // We still want to position to end of the stream.
  622.         err = eofErr;
  623.     }
  624.     else
  625.         err = noErr;
  626.  
  627.     fPosition = newPosition;
  628.     FailOSErr(err);
  629. }
  630.  
  631. //--------------------------------------------------------------------------------------------------
  632. #pragma segment MAStreamUtil
  633.  
  634. pascal void THandleStream::SetSize(long newSize)// override 
  635. {
  636.     SetHandleSize(fHandle, newSize);
  637.     FailMemError();                                // Signal failure if we got a Memory Manager error.
  638.  
  639.     if (newSize < fPosition)                    // If we shrunk the size, then we have to adjust the position.
  640.         fPosition = newSize;
  641. }
  642.  
  643. //--------------------------------------------------------------------------------------------------
  644. #pragma segment MAStreamRead
  645.  
  646. pascal void THandleStream::ReadBytes(void* p,
  647.                                      long count)// override 
  648. {
  649.     long available;
  650.     OSErr err;
  651.  
  652.     available = fSize - fPosition;                // Bytes available in the stream. 
  653.  
  654.     if (available < count)                        // About to read past end of stream. 
  655.     {
  656.         count = available;
  657.         err = eofErr;
  658.     }
  659.     else
  660.         err = noErr;
  661.  
  662.     if (count > 0)                                // Move the bytes. 
  663.     {
  664.         BlockMove((Ptr)(*fHandle + fPosition), (Ptr)p, count);
  665.         fPosition += count;
  666.     }
  667.     else if (count < 0)
  668.         err = paramErr;                            // Negative request count. 
  669.  
  670.     FailOSErr(err);
  671. }
  672.  
  673. //--------------------------------------------------------------------------------------------------
  674. #pragma segment MAStreamWrite
  675.  
  676. pascal void THandleStream::WriteBytes(const void* p,
  677.                                       long count)// override 
  678. {
  679.     long available;
  680.  
  681.     if (count < 0)
  682.         FailOSErr(paramErr);                    // Negtive request count. 
  683.  
  684.     available = fSize - fPosition;                // Bytes available in the stream. 
  685.  
  686.     if (available < count)                        // Grow the handle to accommodate request. 
  687.         this->SetSize(fSize + this->GrowthSize(count - available));
  688.  
  689.     BlockMove(p, (Ptr)(*fHandle + fPosition), count);    // Move the bytes. 
  690.  
  691.     fPosition += count;                            // Advance the position. 
  692.  
  693.     if (fPosition > fSize)                        // Adjust the size if necessary. 
  694.         fSize = fPosition;
  695. }
  696.  
  697. //--------------------------------------------------------------------------------------------------
  698. #pragma segment MAStreamFields
  699.  
  700. pascal void TCountingStream::Fields(TObject* obj)// override 
  701. {
  702.     obj->DoToField("TCountingStream", NULL, bClass);
  703.     obj->DoToField("fPosition", &fPosition, bLongInt);
  704.     obj->DoToField("fSize", &fSize, bLongInt);
  705.  
  706.     inherited::Fields(obj);
  707. }
  708.  
  709. //--------------------------------------------------------------------------------------------------
  710. #pragma segment MAStreamUtil
  711.  
  712. pascal long TCountingStream::GetSize(void)        // override 
  713. {
  714.     return fPosition;
  715. }
  716.  
  717. //--------------------------------------------------------------------------------------------------
  718. #pragma segment MAStreamCreate
  719.  
  720. pascal void TCountingStream::Initialize(void)    // override 
  721. {
  722.     inherited::Initialize();
  723.     fPosition = 0;
  724.     fSize = 0;
  725. }
  726.  
  727. //--------------------------------------------------------------------------------------------------
  728. #pragma segment MAStreamCreate
  729.  
  730. pascal void TCountingStream::ICountingStream(void)
  731. {
  732.     this->IStream();
  733. }
  734.  
  735. //--------------------------------------------------------------------------------------------------
  736. #pragma segment MAStreamWrite
  737.  
  738. pascal void TCountingStream::WriteBytes(const void* /* p */,
  739.                                         long count)// override 
  740. {
  741.     if (count < 0)                                // Can't write negative number of bytes. 
  742.         FailOSErr(paramErr);
  743.  
  744.     fPosition += count;                            // Advance the position. 
  745.  
  746.     if (fPosition > fSize)                        // Adjust the size if necessary. 
  747.         fSize = fPosition;
  748. }
  749.  
  750.  
  751. //--------------------------------------------------------------------------------------------------
  752. #pragma segment MAStreamCreate
  753.  
  754. pascal void TResourceStream::Initialize(void)        // override 
  755. {
  756.     inherited::Initialize();
  757.  
  758.     fResource = NULL;
  759.     fPosition = 0;
  760.     fSize = 0;
  761. }
  762.  
  763. //--------------------------------------------------------------------------------
  764. #pragma segment MAStreamCreate
  765.  
  766. pascal void TResourceStream::IResourceStream(ResType theType, short theID)
  767. {
  768.     if (gConfiguration.systemVersion >= 0x700)
  769.     {
  770.         this->IStream();
  771.         
  772.         Boolean oldResLoad = GetResLoad();
  773.         SetResLoad(FALSE);
  774.         fResource = GetResource(theType, theID);
  775.         SetResLoad(oldResLoad);
  776.         FailNILResource(fResource);
  777.         fSize = SizeResource(fResource);
  778.         FailResError();
  779.     }
  780.     else    // The services in this stream are only available under System 7, so…
  781.         Failure(minErr, 0);                        // !!! need to assign an error constant
  782. }
  783.  
  784. //--------------------------------------------------------------------------------------------------
  785. #pragma segment MAStreamUtil
  786.  
  787. pascal long TResourceStream::GetPosition(void)    // override 
  788. {
  789.     return fPosition;
  790. }
  791.  
  792. //--------------------------------------------------------------------------------------------------
  793. #pragma segment MAStreamUtil
  794.  
  795. pascal void TResourceStream::SetPosition(long newPosition)// override 
  796. {
  797.     fPosition = newPosition;
  798. }
  799.  
  800. //--------------------------------------------------------------------------------------------------
  801. #pragma segment MAStreamUtil
  802.  
  803. pascal long TResourceStream::GetSize(void)
  804. {
  805.     return fSize;
  806. /*
  807.     It's better to maintain our own size, in fSize, than to call SizeResource().
  808.  
  809.     long itsSize = SizeResource(fResource);
  810.     FailResError();
  811.     return itsSize;
  812.  */
  813. }
  814.  
  815. //--------------------------------------------------------------------------------------------------
  816. #pragma segment MAStreamUtil
  817.  
  818. pascal void TResourceStream::SetSize(long newSize)// override 
  819. {
  820.     fSize = newSize;
  821.     SetResourceSize(fResource, newSize);
  822.     FailResError();
  823.  
  824.     if (newSize < fPosition)                    // If we shrunk the size, then we have to adjust the position.
  825.         fPosition = newSize;
  826. }
  827.  
  828. //--------------------------------------------------------------------------------
  829. #pragma segment MASectionWrite
  830.  
  831. pascal void TResourceStream::WriteBytes(const void* p, long count)
  832. {
  833.     register long minSize = this->GetPosition() + count;
  834.     if (minSize > this->GetSize())
  835.         this->SetSize(minSize);                    // increase the size before writing
  836.     WritePartialResource(fResource, this->GetPosition(), p, count);
  837.     FailResError();
  838.  
  839.     this->SetPosition(minSize);                    // Advance the position. 
  840. }
  841.  
  842. //--------------------------------------------------------------------------------------------------
  843. #pragma segment MAStreamRead
  844.  
  845. pascal void TResourceStream::ReadBytes(void* p, long count)    // override 
  846. {
  847.     register long minToRead = Min(count, this->GetSize() - this->GetPosition());
  848.     ReadPartialResource(fResource, this->GetPosition(), p, minToRead);
  849.     FailResError();
  850.  
  851.     this->SetPosition(this->GetPosition() + count);        // Advance the position. 
  852. }
  853.  
  854.